<h3>Chapter 2: About programs</h3>
<p>
The title of this chapter of the textbook is actually poorly named,
since one does not write programs in LPC. An LPC coder instead
writes <B>objects</B>. What is the difference? Well, for our purposes
now, the difference is in the way the file is executed. When you
&quot;run&quot; a program, execution begins at a definite place
in the program. In other words, there is a place in all programs
that is noted as the beginning where program execution starts.
In addition, programs have definite end points, so that when execution
reaches that point, the execution of the program terminates. So,
in short, execution of a program runs from a definite beginning
point through to a definite end point. This is not so with LPC
objects.
</p>
<p>
With muds, LPC objects are simply distinct parts of the C program
which is running the game (the driver). In other words, execution
of the mud program begins and ends in the driver. But the driver
in fact does very little in the way of creating the world you
know when you play a mud. Instead, the driver relies heavily on
the code created in LPC, executing lines of the objects in the
mud as needed. LPC objects thus have no place that is necessarily
the beginning point, nor do they have a definite ending point.
</p>
</p>
Like other programming languages, an LPC &quot;program&quot; may
be made up of one or more files. For an LPC object to get executed,
it simple needs to be loaded into the driver's memory. The driver
will call lines from the object as it needs according to a structure
which will be defined throughout this textbook. The important thing you need
to understand at this point is that there is no &quot;beginning&quot;
to an LPC object in terms of execution, and there is no &quot;end&quot;.
</p>
<hr size="1">
<p><strong>Driver-mudlib interaction</strong></p>
<p>
As I have mentioned earlier, the driver is the C program that
runs on the host machine. It connects you into the game and processes
LPC code. Note that this is one theory of mud programming, and
not necessarily better than others. It could be that the entire
game is written in C. Such a game would be much faster, but it
would be less flexible in that wizards could not add things to
the game while it was running. This is the theory behind DikuMUDs.
Instead, LPMUDs run on the theory that the driver should in no
define the nature of the game, that the nature of the game is
to be decided by the individuals involved, and that you should
be able to add to the game <I>as it is being played</I>. This
is why LPMUDs make use of the LPC programming language. It allows
you to define the nature of the game in LPC for the driver to
read and execute as needed. It is also a much simpler language
to understand than C, thus making the process of world creation
open to a greater number of people.
</p>
<p>
Once you have written a file in LPC (assuming it is correct LPC
), it just sits there on the host machine's hard drive until something
in the game makes reference to it. When something in the game
finally does make reference to the object, a copy of the file
is loaded into memory and a special function of that object is
called in order to initialize the values of the variables in the
object. Now, do not be concerned if that last sentence went right
over your head, since someone brand new to programming would not
know what the hell a function or a variable is. The important
thing to understand right now is that a copy of the object file
is taken by the driver from the machine's hard drive and stored
into memory (since it is a copy, multiple versions of that object
may exist). You will later understand what a function is, what
a variable is, and exactly how it is something in the game made
reference to your object.
</p>
<hr size="1">
<p><strong>Loading an object into memory</strong></p>
<p>
Although there is no particular place in an object code that must
exist in order for the driver to begin executing it, there is
a place for which the driver will search in order to initialize
the object. On compat drivers, it is the function called reset().
On native muds it is the function called create().
</p>
<p>
LPC objects are made up of variables (values which can change)
and functions which are used to manipulate those variables. Functions
manipulate variables through the use of LPC grammatical structures,
which include calling other functions, using externally defined
functions (efuns), and basic LPC expressions and flow control
mechanisms.
</p>
<p>
Does that sound convoluted? First lets start with a variable.
A variable might be something like: level. It can &quot;vary&quot;
from situation to situation in value, and different things use
the value of the player's level to make different things happen.
For instance, if you are a level 19 player, the value of the variable
level will be 19. Now if your mud is on the old LPMud 2.4.5 system
where levels 1-19 are players and 20+ are wizards, things can
ask for your level value to see if you can perform wizard type
actions. Basically, each object in LPC is a pile of variables
with values which change over time.
</p>
<p>
Things happen to these objects based on what values its variables
hold. Often, then things that happen cause the variables to change.
</p>
<p>
So, whenever an object in LPC is referenced by another object
currently in memory, the driver searches to see what places for
values the object has (but they have no values yet). Once that
is done, the driver calls a function in the object called reset()
or create() (depending on your driver) which will set up the starting
values for the object's variables. It is thus through calls to
functions that variable values get manipulated.
</p>
<p>
But create() or reset() is NOT the starting place of LPC code,
although it is where most LPC code execution does begin. The fact
is, those functions need not exist. If your object does just fine
with its starting values all being NULL pointers (meaning, for
our purposes here, 0), then you do not need a create() or reset()
function. Thus the first bit of execution of the object's code
may begin somewhere completely different.
</p>
<p>
Now we get to what this chapter is all about. The question: What
consists a complete LPC object? Well, an LPC object is simply
one or more functions grouped together manipulating 0 or more
variables. The order in which functions are placed in an object
relative to one another is irrelevant. In other words:
<pre>
void init() {
    add_action(&quot;smile&quot;, &quot;smile&quot;);
}

void create() {
    return;
}

int smile( string str ) {
    return 0;
}
</pre>
is exactly the same as:
<pre>
void create() {
    return;
}

int smile( string str ) {
    return 0;
}

void init() {
    add_action(&quot;smile&quot;, &quot;smile&quot;);
}
</pre>
Also important to note, the object containing only:
<pre>
void nonsense() {}
</pre>
is a valid, but trivial object, although it probably would not
interact properly with other objects on your mud since such an
object has no weight, is invisible, etc..
</p>
<hr size="1">
<p><strong>Chapter Summary</strong></p>
<p>
LPC code has no beginning point or ending point, since LPC code
is used to create objects to be used by the driver program rather
than create individual programs. LPC objects consist of one or
more functions whose order in the code is irrelevant, as well
as of zero or more variables whose values are manipulated inside
those functions. LPC objects simply sit on the host machine's
hard driver until referenced by another object in the game (in
other words, they do not really exist). Once the object is referenced,
it is loaded into the machine's memory with empty values for the
variables. The function reset() in compat muds or create() in
native muds is called in that object if it exists to allow the
variables to take on initial values. Other functions in the object
are used by the driver and other objects in the game to allow
interaction among objects and the manipulation of the LPC variables.
</p>
<p>
A note on reset() and create():
<blockquote>
create() is only used by muds in native mode (see the textbook
Introduction for more information on native mode vs. compat mode).
It is only used to initialize newly referenced objects.
</blockquote>
<blockquote>
reset() is used by both muds in compat mode and native mode. In
compat mode, reset() performs two functions. First, it is used
to initialize newly referenced objects. In addition, however,
compat mode muds use reset() to &quot;reset&quot; the object.
In other words, return it to its initial state of affairs. This
allows monsters to regenerate in a room and doors to start back
in the shut position, etc.. Native mode muds use reset() to perform
the second function (as its name implies).
</blockquote>
</p>
<p>
So there are two important things which happen in LP style muds
which cause the driver to make calls to functions in objects.
The first is the creation of the object. At this time, the driver
calls a function to initalize the values in the object. For compat
mode muds, this is performed by the function named reset() (with
an argument of 0, more on this later though). For muds running
in native mode, this is performed by the function create().
</p>
<p>
The second is the returning of the room to some base state of
affairs. This base set of affairs may or may not be different
from the initial state of affairs, and certainly you would not
want to take up time doing redundant things (like resetting variables
that never change). Compat mode muds nevertheless use the same
function that was used to create the object to reset it, that
being reset(). Native mode muds, who use create() to create the
room, instead use reset() to reset it. All is not lost in compat
mode though, as there is a way to tell the difference between
creation and resetting. For reset purposes, the driver passes
either 1 or the reset number as an argument to reset() in compat
mode. Now this is meaningless to you now, but just keep in mind
that you can in fact tell the difference in compat mode. Also
keep in mind that the argment in the creation use of reset is
0 and the argument in the reset use is a nonzero number.
</p>
